home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-02-25 | 11.7 KB | 439 lines | [TEXT/ttxt] |
- #========================================================================
- # Function: CheckAttributes
- # Purpose: If the tag has attributes, check them for validity.
- #========================================================================
- sub CheckAttributes
- {
- undef %args;
-
- if ($closing == 0 && $tag =~ m|^(\S+)\s+(.*)|)
- {
- ($id,$tail) = ($1,$2);
- $ID = "\U$id";
- $tail =~ s/\n/ /g;
-
- # check for odd number of quote characters
- ($quotes = $tail) =~ s/[^"]//g;
- &whine($., 'odd-quotes', $tag) if length($quotes) % 2 == 1;
-
- $novalue = 0;
- $valid = $validAttributes{$ID};
- while ($tail =~ /^\s*([^=\s]+)\s*=\s*(.*)$/
- # catch attributes like ISMAP for IMG, with no arg
- || ($tail =~ /^\s*(\S+)(.*)/ && ($novalue = 1)))
- {
- $arg = "\U$1";
- $rest = $2;
-
- &whine($., 'unexpected-open', $tag) if $arg =~ /</;
-
- if ($arg !~ /^($valid)$/i && $ID =~ /^($legalElements)$/o)
- {
- if ($arg =~ /^($netscapeAttributes{$ID})$/i)
- {
- &whine($., 'netscape-attribute', $arg, $id);
- }
- else
- {
- &whine($., 'unknown-attribute', $id, $arg);
- }
- }
-
- #-- catch repeated attributes. for example:
- #-- <IMG SRC="foo.gif" SRC="bar.gif">
- if (defined $args{$arg})
- {
- &whine($., 'repeated-attribute', $arg, $id);
- }
-
- if ($novalue)
- {
- $args{$arg} = '';
- $tail = $rest;
- }
- elsif ($rest =~ /^'([^']+)'(.*)$/)
- {
- &whine($., 'attribute-delimiter', $arg, $ID);
- $args{$arg} = $1;
- $tail = $2;
- }
- elsif ($rest =~ /^"([^"]+)"(.*)$/
- || $rest =~ /^'([^']+)'(.*)$/
- || $rest =~ /^(\S+)(.*)$/)
- {
- $args{$arg} = $1;
- $tail = $2;
- }
- else
- {
- $args{$arg} = $rest;
- $tail = '';
- }
- $novalue = 0;
- }
- foreach $attr (keys %args)
- {
- if (defined $attributeFormat{$attr} &&
- $args{$attr} !~ /^($attributeFormat{$attr})$/i)
- {
- &whine($., 'attribute-format', $attr, $id, $args{$attr});
- }
- }
- &whine($., 'unexpected-open', $tag) if $tail =~ /</o;
- }
- else
- {
- if ($closing && $id =~ m|^(\S+)\s+(.*)|)
- {
- &whine($., 'closing-attribute', $tag);
- $id = $1;
- }
- $ID = "\U$id";
- }
- }
-
- #========================================================================
- # Function: whine
- # Purpose: Give a standard format whine:
- # filename(line #): <message>
- # The associative array `enabled' is used as a gating
- # function, to suppress or enable each warning. Every
- # warning has an associated identifier, which is used to
- # refer to the warning, and as the index into the hash.
- #========================================================================
- sub whine
- {
- local($line, $id, @argv) = @_;
- local($mstyle) = $variable{'message-style'};
-
- ## JS 2-4-96
- ## Added the following lines so that the results would be saved to a file
- ## this is nice for the mac version.
- ## The results file is saved in the same folder as MacWebLint
- open (OUTFILE, ">>$gResults") || die "Cannot open gResults: $!\n";
-
- return unless $enabled{$id};
- $exit_status = 1;
-
- ## JS 12-6-95
- ## rewritten to output to a text file cause this is the way that
- ## I want it to work. this is the best way that I know how to do it.
-
- if ($mstyle eq 'terse') {
- print "$filename:$line:$id\n";
- print OUTFILE "$filename:$line:$id\n";
- return; }
-
- if ($mstyle eq 'lint') {
- (eval "print \"$filename($line): $message{$id}\n\"");
- (eval "print OUTFILE \"$filename($line): $message{$id}\n\"");
- return; }
-
- if ($mstyle eq 'short') {
- (eval "print \"line $line: $message{$id}\n\"");
- (eval "print OUTFILE \"line $line: $message{$id}\n\"");
- return; }
-
- close (OUTFILE);
-
- # JS 12-6-95
- # commented this out because it is re-done above
- # (print "$filename:$line:$id\n"), return if $mstyle eq 'terse';
- # (eval "print \"$filename($line): $message{$id}\n\""), return if $mstyle eq 'lint';
- # (eval "print \"line $line: $message{$id}\n\""), return if $mstyle eq 'short';
-
- die "Unknown message style `$mstyle'\n";
- }
-
-
- #========================================================================
- # Function: GetConfigFile
- # Purpose: Read user's configuration file, if such exists.
- # If WEBLINTRC is set in user's environment, then read the
- # file referenced, otherwise try for $HOME/.weblintrc.
- #========================================================================
- sub GetConfigFile
- {
- local(*CONFIG);
- local($filename);
- local($arglist);
- local($value);
-
-
- # JS 2-4-96
- # this is the config file for MacWebLint.
- $filename = "MacWebLint.rc";
- return unless -f $filename;
-
- open(CONFIG,"< $filename") || do
- {
- print WARNING "Unable to read config file `$filename': $!\n";
- return 0;
- };
-
- while (<CONFIG>)
- {
- s/#.*$//;
- next if /^\s*$/o;
-
- #-- match keyword: process one or more argument -------------------
- if (/^\s*(enable|disable|extension|ignore)\s+(.*)$/io)
- {
- $keyword = "\U$1";
- $arglist = $2;
- while ($arglist =~ /^\s*(\S+)/o)
- {
- $value = "\L$1";
-
- &enableWarning($1, 1) if $keyword eq 'ENABLE';
-
- &enableWarning($1, 0) if $keyword eq 'DISABLE';
-
- $ignore{"\U$1"} = 1 if $keyword eq 'IGNORE';
-
- &AddExtension("\L$1") if $keyword eq 'EXTENSION';
-
- $arglist = $';
- }
- }
- elsif (/^\s*set\s+(\S+)\s*=\s*(.*)/)
- {
- # setting a weblint variable
- if (defined $variable{$1})
- {
- $variable{$1} = $2;
- }
- else
- {
- print WARNING "Unknown variable `$1' in configuration file\n";
- }
- }
- }
-
- close CONFIG;
-
- 1;
- }
-
- sub enableWarning
- {
- local($id, $enabled) = @_;
-
-
- if (! defined $enabled{$id})
- {
- print WARNING "$PROGRAM: unknown warning identifier \"$id\"\n";
- return 0;
- }
-
- $enabled{$id} = $enabled;
-
- #
- # ensure consistency: if you just enabled upper-case,
- # then we should make sure that lower-case is disabled
- #
- $enabled{'lower-case'} = 0 if $_ eq 'upper-case';
- $enabled{'upper-case'} = 0 if $_ eq 'lower-case';
- $enabled{'upper-case'} = $enabled{'lower-case'} = 0 if $_ eq 'mixed-case';
-
- return 1;
- }
-
- #========================================================================
- # Function: AddExtension
- # Purpose: Extend the HTML understood. Currently supported extensions:
- # netscape - the netscape extensions proposed by
- # Netscape Communications, Inc. See:
- # http://www.netscape.com/home/services_docs/html-extensions.html
- #========================================================================
- sub AddExtension
- {
- local($extension) = @_;
- local(@extlist);
- local($element);
-
- if ($extension =~ /,/)
- {
- @extlist = split(/\s*,\s*/, $extension);
- &AddExtension(shift @extlist) while @extlist > 0;
- return;
- }
-
- if ($extension ne 'netscape' && $extension ne 'java')
- {
- warn "$PROGRAM: unknown extension `$extension' -- ignoring.\n";
- return;
- }
-
- #---------------------------------------------------------------------
- # java extensions
- #---------------------------------------------------------------------
-
- if ($extension eq 'java')
- {
- $legalElements .= '|'.$javaElements;
- $pairElements .= '|APPLET';
-
- &AddAttributes('APPLET', 'CODEBASE', 'CODE', 'ALT', 'NAME',
- 'WIDTH', 'HEIGHT', 'ALIGN', 'VSPACE', 'HSPACE');
- &AddAttributes('PARAM', 'NAME', 'VALUE');
-
- $requiredContext{'PARAM'} = 'APPLET';
- $requiredAttributes{'APPLET'} = 'CODE|WIDTH|HEIGHT';
- $requiredAttributes{'PARAM'} = 'NAME|VALUE';
-
- return;
- }
-
- #---------------------------------------------------------------------
- # netscape extensions
- #---------------------------------------------------------------------
-
- #-- new element attributes for existing elements ---------------------
- foreach $element (keys %netscapeAttributes)
- {
- &AddAttributes($element, split(/\|/, $netscapeAttributes{$element}));
- }
-
- #-- formats for new attributes ---------------------------------------
-
- $attributeFormat{'SIZE'} = '[-+]?\d+';
- $attributeFormat{'MARGINWIDTH'} = '\d+';
- $attributeFormat{'MARGINHEIGHT'} = '\d+';
- $attributeFormat{'SCROLLING'} = 'NO|YES|AUTO';
- $attributeFormat{'WIDTH'} = '\d+%?';
-
- #-- new elements -----------------------------------------------------
-
- $legalElements .= '|'.$netscapeElements;
- $pairElements .= '|BLINK|CENTER|FONT|FRAMESET|NOFRAMES|NOBR|MAP|SCRIPT';
- $requiredContext{'AREA'} = 'MAP';
- $requiredContext{'FRAME'} = 'FRAMESET';
- $requiredAttributes{'MAP'} = 'NAME';
- $requiredAttributes{'AREA'} = 'COORDS';
-
- $okInHead{'SCRIPT'} = 1;
- }
-
- sub AddAttributes
- {
- local($element,@attributes) = @_;
- local($attr);
-
-
- $attr = join('|', @attributes);
- if (defined $validAttributes{$element})
- {
- $validAttributes{$element} .= "|$attr";
- }
- else
- {
- $validAttributes{$element} = "$attr";
- }
- }
-
- #========================================================================
- # Function: ListWarnings()
- # Purpose: List all supported warnings, with identifier, and
- # whether the warning is enabled.
- #========================================================================
- sub ListWarnings
- {
- local($id);
- local($message);
-
-
- foreach $id (sort keys %enabled)
- {
- ($message = $message{$id}) =~ s/\$argv\[\d+\]/.../g;
- $message =~ s/\\"/"/g;
- print WARNING "$id (", ($enabled{$id} ? "enabled" : "disabled"), ")\n";
- print WARNING " $message\n\n";
- }
- }
-
- sub CheckURL
- {
- local($url) = @_;
- local($workfile) = "$TMPDIR/$PROGRAM.$$";
- local($urlget) = $variable{'url-get'};
-
-
- die "$PRORGAM: url-get variable is not defined -- ".
- "don't know how to get $url\n" unless defined $urlget;
-
- system("$urlget $url > $workfile");
- &WebLint($workfile, $url);
- unlink $workfile;
- }
-
- sub PrintToDo
- {
- die "$todo" unless defined $variable{'url-get'};
- print "[grabbing weblint todo list - $ToDoURL]\n";
- system("$variable{'url-get'} $ToDoURL");
- }
-
- #========================================================================
- # Function: wanted
- # Purpose: This is called by &find() to determine whether a file
- # is wanted. We're looking for files, with the filename
- # extension .html or .htm.
- #========================================================================
- # JS - 2-4-96
- # I completely re-wrote this function so that it would work correctly
- # the way that I wanted it to work. I guess it changed between the 1.011
- # and this version to support more than one index.html filename. Unfortunately,
- # it did not seem to work correctly on the Mac. While my version may not
- # be the fastest, it seems to work, which is more important to me. :)
-
- sub wanted
- {
- local($foundIndex);
-
- if ( -d $name )
- {
- $foundIndex = 0;
- foreach $legalIndex (@dirIndices)
- {
- if ( -f ("$name" . ":" . "$legalIndex") )
- {
- $foundIndex=1;
- last;
- }
- }
- if (! $foundIndex)
- {
- &whine("$name", 'directory-index', "@dirIndices");
- }
- }
-
- /\.(html|htm)$/ && # valid filename extensions: .html .htm
- -f $_ && # only looking for files
- (!$opt_l || !-l $_) && # ignore symlinks if -l given
- &WebLint($_,$name); # check the file
- }
-
- sub PopEndTag
- {
- $matched = pop @tags;
- pop @tagNums;
- $matchedLine = pop @taglines;
-
- #-- does top of stack match top of orphans stack? --------
- while (@orphans > 0 && @tags > 0
- && $orphans[$#orphans] eq $tags[$#tags])
- {
- &whine($., 'element-overlap', $orphans[$#orphans],
- $orphanlines[$#orphanlines], $matched, $matchedLine);
- pop @orphans;
- pop @orphanlines;
- pop @tags;
- pop @tagNums;
- pop @taglines;
- }
- $tagRE = join('|',@tags);
- }
-
- 1;
-